#ifndef AIO_INCLUDED_H_
#define AIO_INCLUDED_H_

// Copyright (c) 2011, Jasper Bekkers
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL JASPER BEKKERS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#define MAX_AIO 256
#define MAX_AIO_REQUESTS 64

#ifndef AIO_ALIGN
#define AIO_ALIGN(x) __declspec(align(x))
#endif

#ifndef AIO_ASSERT
#include <assert.h>
#define AIO_ASSERT(x, msg, ...) do{ assert(x); } while(0);
#endif

// Notes:
//
//  - Cancelling pending I/O requests is only(correctly) implemented
//    in Windows versions Vista and newer (eg. no XP support)
//    since my dev machine is (still) an XP machine there is currently
//    no support for cancelling I/O requests.
//
//  - To prevent ERROR_NO_SYSTEM_RESOURCES (from GetLastError()) after
//    a call to aioRead or aioWrite, make sure that you are transferring
//    less than 63.95MB on IA-32 and IA-64 and less than (a little under)
//    32MB on X64. If you do encounter this issue, split the I/O requests
//    up into smaller parts of 16MB.
//
//  - It is advised that you initialize with the default number of threads,
//    however, because callbacks are handled in the Async I/O thread you 
//    might want to bump the number of active threads if your callbacks 
//    take a long time to execute and/or you have a lot of I/O going on.

struct Aio {
	int fd;
	unsigned int offset;
	unsigned int size;
	void *buf;
	void *usrdata;
};

enum AioErrorCode {
	Succeeded,
	InvalidArgument,
	InvalidPath,
	GenericIOError,
	AioAlreadyInitialized,
	AioNotInitialized,
	MaxFilesOpened,
	MaxRequestsReached
};

enum {
	AioRead = 1,
	AioWrite = 2,
};

typedef void (*AioCallback)(Aio *aio, AioErrorCode error, int id, unsigned int size);

AioErrorCode aioInit(unsigned int numthreads = 1);
AioErrorCode aioOpen(const char *path, int flags, int *fd, void *args);
AioErrorCode aioRead(Aio *aio, int *id, AioCallback callback);
AioErrorCode aioWrite(Aio *aio, int *id, AioCallback callback);
AioErrorCode aioClose(int fd);
AioErrorCode aioFinish();

#endif
